﻿// Copyright 2009 Mike Geise
// 
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// 
//     http://www.apache.org/licenses/LICENSE-2.0
// 
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

namespace Falcon.Core.Services
{
	using System;
	using System.Drawing;
	using System.Drawing.Drawing2D;
	using System.Drawing.Imaging;
	using System.IO;
	using System.Web;
	using Falcon.Core.Domain.Results;
	using Falcon.Core.Domain.Services;
	using Falcon.Core.Extensions;

	public class ImageService : IImageService
	{
		public ImageResult Save(HttpPostedFileBase file, string path)
		{
			return Save(file, null, path, Guid.NewGuid().ToString());
		}

		public ImageResult Save(HttpPostedFileBase file, string path, string name)
		{
			return Save(file, null, path, name);
		}

		public ImageResult Save(HttpPostedFileBase file, ImageFormat format, string path)
		{
			return Save(file, format, path, Guid.NewGuid().ToString());
		}

		public ImageResult Save(HttpPostedFileBase file, ImageFormat format, string path, string name)
		{
			if (file == null)
			{
				throw new ArgumentNullException("file");
			}

			var nameOnDisk = string.Concat(name, (format == null) ? Path.GetExtension(file.FileName) : GetExt(format));
			var typeOnDisk = (format == null) ? file.ContentType : GetContentType(format);

			var result = new ImageResult
         	{
				FileName = Path.GetFileName(file.FileName),
				FileDiskName = nameOnDisk,
				FileExtension = Path.GetExtension(file.FileName).Replace(".", string.Empty),
				FilePath = Path.Combine(path, nameOnDisk),
				FileType = typeOnDisk
         	};

			using (var image = Image.FromStream(file.InputStream))
			{
				result.Width = image.Width;
				result.Height = image.Height;

				if (format == null)
				{
					image.Save(result.FilePath.AsPath());
				}
				else
				{
					image.Save(result.FilePath.AsPath(), format);
				}

				image.Dispose();
			}

			return result;
		}

		public void Resize(string name, string source, string path, int width, int height, bool aspect)
		{
			using (var image = Image.FromFile(source.AsPath()))
			{
				Resize(image, null, path, width, height, aspect);
			}
		}

		public void Resize(HttpPostedFileBase file, string name, string path, int width, int height, bool aspect)
		{
			using (var image = Image.FromStream(file.InputStream))
			{
				Resize(image, null, path, width, height, aspect);
			}
		}

		public void Resize(HttpPostedFileBase file, ImageFormat format, string name, string path, int width, int height, bool aspect)
		{
			using (var image = Image.FromStream(file.InputStream))
			{
				Resize(image, format, path, width, height, aspect);
			}
		}

		private static void Resize(Image image, ImageFormat format, string path, int width, int height, bool aspect)
		{
			using (var orignal = new Bitmap(image))
			{
				if (orignal.Width < width && orignal.Height < height)
				{
					orignal.Save(path.AsPath(), format ?? image.RawFormat);
				}

				var wi = width;
				var hi = height;

				if (aspect)
				{
					if (orignal.Width > orignal.Height)
					{
						wi = width;
						hi = (int)(orignal.Height * ((decimal)width / orignal.Width));
					}
					else
					{
						hi = height;
						wi = (int)(orignal.Width * ((decimal)height / orignal.Height));
					}
				}

				using (var thumbnail = new Bitmap(wi, hi))
				{
					using (var graphic = Graphics.FromImage(thumbnail))
					{
						graphic.InterpolationMode = InterpolationMode.HighQualityBicubic;
						graphic.FillRectangle(Brushes.White, 0, 0, wi, hi);
						graphic.DrawImage(orignal, 0, 0, wi, hi);

						thumbnail.Save(path.AsPath(), image.RawFormat);

						graphic.Dispose();
					}

					thumbnail.Dispose();
				}

				orignal.Dispose();
			}

			image.Dispose();
		}

		private static string GetExt(ImageFormat format)
		{
			if (format == ImageFormat.Bmp)
			{
				return ".bmp";
			}

			if (format == ImageFormat.Gif)
			{
				return ".gif";
			}

			return format == ImageFormat.Png ? ".png" : ".jpeg";
		}

		private static string GetContentType(ImageFormat format)
		{
			if (format == ImageFormat.Bmp)
			{
				return "image/bmp";
			}

			if (format == ImageFormat.Gif)
			{
				return "image/gif";
			}

			return format == ImageFormat.Png ? "image/png" : "image/pjpeg";
		}
	}
}